import React, { useEffect, useRef, useState } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Platform, Alert } from 'react-native';
import { io, Socket } from 'socket.io-client';
import {
  RTCPeerConnection,
  RTCIceCandidate,
  RTCSessionDescription,
  RTCView,
  mediaDevices,
  MediaStream,
  MediaStreamTrack,
} from 'react-native-webrtc';


interface VideoConstraints {
  width: { min: number };
  height: { min: number };
  frameRate: { min: number };
  facingMode: string;
}

// Socket.IO 服务器配置
const SOCKET_SERVER = 'http://192.168.46.222:3001'

export default function EbRTCVideo() {
  let remoteUserId='用户A'
  let localUserId='用户B'
  const [localStream, setLocalStream] = useState<MediaStream | null>(null);
  const [remoteStream, setRemoteStream] = useState<MediaStream | null>(null);
  const [isCallActive, setIsCallActive] = useState(false);
  const [isConnected, setIsConnected] = useState(false);
  const [isIncomingCall, setIsIncomingCall] = useState(false);
  const [isOutgoingCall, setIsOutgoingCall] = useState(false);
  const [callStatus, setCallStatus] = useState<string>('');
  const [isLocalVideoMain, setIsLocalVideoMain] = useState(true);
  const peerConnectionRef = useRef<RTCPeerConnection | null>(null);
  const socketRef = useRef<Socket | null>(null);
  const pendingOfferRef = useRef<RTCSessionDescription | null>(null);
  const pendingIceCandidatesRef = useRef<RTCIceCandidate[]>([]);

  useEffect(() => {
    // 初始化 Socket.IO 连接
    socketRef.current = io(SOCKET_SERVER, {
      transports: ['websocket'],
      reconnection: true,
      reconnectionAttempts: 5,
      reconnectionDelay: 1000,
    });

    // 监听连接状态
    socketRef.current.on('connect', () => {
      console.log('Socket.IO 连接成功');
      setIsConnected(true);
    });

    socketRef.current.on('disconnect', () => {
      console.log('Socket.IO 连接断开');
      setIsConnected(false);
    });

    socketRef.current.on('connect_error', (error) => {
      console.error('Socket.IO 连接错误:', error);
    });
    
    // 加入房间
    socketRef.current.emit('join', { userId: localUserId });

    // 初始化本地媒体流
    const initializeMedia = async () => {
      try {
        const stream = await mediaDevices.getUserMedia({
          audio: true,
          video: {
            width: { min: 640 },
            height: { min: 480 },
            frameRate: { min: 30 },
            facingMode: 'user',
          } as VideoConstraints,
        });
        setLocalStream(stream);
        console.log('本地媒体流已设置:', stream);
      } catch (err) {
        console.error('获取媒体设备失败:', err);
      }
    };

    initializeMedia();

    // 处理视频通话信令
    socketRef.current.on('video-offer', async (data) => {
      console.log('收到视频请求:', data);
      console.log('当前状态 - localUserId:', localUserId, 'remoteUserId:', remoteUserId, 'isOutgoingCall:', isOutgoingCall);

      // 只有当收到的视频请求是发给当前用户（data.to === localUserId）
      // 并且请求来自我们正在通话的远程用户（data.from === remoteUserId）时，才进一步处理。
      if (data.to === localUserId && data.from === remoteUserId) {
        // 如果当前用户正在发起通话（即是呼叫方），则忽略收到的来电请求，防止重复提示。
        if (isOutgoingCall) {
          console.log('当前正在发起通话，忽略收到的来电请求。');
          return;
        }

        setIsIncomingCall(true);
        setCallStatus('收到来电');
        pendingOfferRef.current = new RTCSessionDescription(data.sdp);
      } else {
        console.log('收到的视频请求不符合当前用户的接收条件或为无效请求。忽略。');
      }
    });

    socketRef.current.on('video-answer', async (data) => {
      console.log('收到视频应答:', data);
      if (data.from === remoteUserId) {
        try {
          console.log('视频应答处理：检查 peerConnectionRef.current:', peerConnectionRef.current);
          if (!peerConnectionRef.current) {
            console.error('Peer connection not initialized');
            return;
          }

          const pc = peerConnectionRef.current;
          let signalingState = pc.signalingState;
          console.log('视频应答处理：当前 signalingState (before setRemoteDescription):', signalingState);
          
          // Only set remote description if we're in the right state
          if (signalingState === 'have-local-offer') {
            await pc.setRemoteDescription(new RTCSessionDescription(data.sdp));
            console.log('视频应答处理：设置远程描述后 signalingState:', pc.signalingState);
            console.log('视频应答处理：准备添加ICE候选，当前 connectionState:', pc.connectionState, 'iceConnectionState:', pc.iceConnectionState);
            setIsCallActive(true);
            setIsOutgoingCall(false);
            setCallStatus('通话中');
            setIsLocalVideoMain(false);

            // Add any queued ICE candidates after setting remote description for the caller
            if (pendingIceCandidatesRef.current.length > 0) {
              console.log('Adding queued ICE candidates after setting remote description for caller');
              for (const candidate of pendingIceCandidatesRef.current) {
                console.log('准备添加ICE候选 (应答处理): current connectionState:', pc.connectionState, 'iceConnectionState:', pc.iceConnectionState);
                await pc.addIceCandidate(candidate);
                console.log('成功添加ICE候选 (应答处理):', candidate);
              }
              pendingIceCandidatesRef.current = [];
            }

          } else {
            console.warn('Cannot set remote answer in current state:', signalingState);
          }
        } catch (err) {
          console.error('处理视频应答失败:', err);
          cleanupCall();
        }
      }
    });

    socketRef.current.on('ice-candidate', async (data) => {
      console.log('收到ICE候选:', data);
      if (data.from === remoteUserId && peerConnectionRef.current) {
        try {
          const pc = peerConnectionRef.current;
          const candidate = new RTCIceCandidate(data.candidate);

          // If remote description is not set yet, queue the candidate
          if (!pc.remoteDescription || !pc.remoteDescription.type) {
            console.log('Remote description not set, queueing ICE candidate');
            pendingIceCandidatesRef.current.push(candidate);
            return;
          }

          // If we have queued candidates, add them first
          if (pendingIceCandidatesRef.current.length > 0) {
            console.log('Adding queued ICE candidates');
            for (const queuedCandidate of pendingIceCandidatesRef.current) {
              console.log('准备添加ICE候选 (队列):', queuedCandidate, 'current connectionState:', pc.connectionState, 'iceConnectionState:', pc.iceConnectionState);
              await pc.addIceCandidate(queuedCandidate);
            }
            pendingIceCandidatesRef.current = [];
          }

          // Add the new candidate
          console.log('准备添加ICE候选 (新):', candidate, 'current connectionState:', pc.connectionState, 'iceConnectionState:', pc.iceConnectionState);
          await pc.addIceCandidate(candidate);
          console.log('成功添加ICE候选 (新):', candidate);
        } catch (err) {
          console.error('处理ICE候选失败:', err);
        }
      }
    });

    socketRef.current.on('call-rejected', (data) => {
      console.log('通话被拒绝:', data);
      if (data.from === remoteUserId) {
        Alert.alert('提示', '对方拒绝了通话');
        cleanupCall();
      }
    });

    socketRef.current.on('hangup', (data) => {
      console.log('收到挂断请求:', data);
      if (data.from === remoteUserId) {
        Alert.alert('提示', '对方已挂断通话');
        cleanupCall();
      }
    });

    return () => {
      cleanupCall();
    };
  }, [localUserId, remoteUserId]);

  const createPeerConnection = (currentLocalStream: MediaStream | null) => {
    const configuration = {
      iceServers: [
        { urls: 'stun:stun.l.google.com:19302' },
      ],
    };
    const pc = new RTCPeerConnection(configuration);
    console.log('RTCPeerConnection 实例已创建:', pc);

    if (currentLocalStream) {
      console.log('尝试从 localStream 添加轨道. 轨道数量:', currentLocalStream.getTracks().length);
      currentLocalStream.getTracks().forEach(track => {
        pc.addTrack(track, currentLocalStream);
      });
    } else {
      console.warn('创建 PeerConnection 时 localStream 不可用，无法添加媒体轨道。');
    }

    // 监听 ICE 连接状态变化
    (pc as any).oniceconnectionstatechange = () => {
      console.log('ICE 连接状态变化:', pc.iceConnectionState);
      if (pc.iceConnectionState === 'connected' || pc.iceConnectionState === 'completed') {
        console.log('ICE 连接成功建立！');
      } else if (pc.iceConnectionState === 'failed') {
        console.error('ICE 连接失败！');
        // 可以考虑在此处触发重新连接或清理
      }
    };

    // 监听 PeerConnection 整体连接状态变化
    (pc as any).onconnectionstatechange = () => {
      console.log('PeerConnection 整体连接状态变化:', pc.connectionState);
      if (pc.connectionState === 'disconnected' || pc.connectionState === 'failed' || pc.connectionState === 'closed') {
        console.error('PeerConnection 连接已断开、失败或已关闭。状态:', pc.connectionState);
      }
    };

    // 监听 SDP 协商是否需要
    (pc as any).onnegotiationneeded = () => {
      console.log('PeerConnection 需要协商 (onnegotiationneeded)');
    };

    // 兼容类型声明，监听远程流
    (pc as any).ontrack = (event: any) => {
      console.log('收到远程流:', event);
      if (event.streams && event.streams[0]) {
        setRemoteStream(event.streams[0]);
        console.log('远程流已设置');
      } else {
        console.warn('ontrack事件未包含有效的流或 streams[0] 不可用. Event:', event);
      }
    };

    // 监听 ICE
    (pc as any).onicecandidate = (event: any) => {
      console.log('本地ICE候选:', event);
      if (event.candidate) {
        socketRef.current?.emit('ice-candidate', {
          candidate: event.candidate,
          to: remoteUserId,
          from: localUserId,
        });
      }
    };

    return pc;
  };

  const handleIncomingCall = async () => {
    try {
      console.log('处理来电：开始处理');
      if (!peerConnectionRef.current) {
        peerConnectionRef.current = createPeerConnection(localStream);
        console.log('处理来电：peerConnectionRef.current 已创建', peerConnectionRef.current);
      }
      
      if (pendingOfferRef.current) {
        console.log('处理来电：设置远程描述前 signalingState:', peerConnectionRef.current.signalingState);
        await peerConnectionRef.current.setRemoteDescription(pendingOfferRef.current);
        console.log('处理来电：设置远程描述后 signalingState:', peerConnectionRef.current.signalingState);
        
        // Add any queued ICE candidates after setting remote description
        if (pendingIceCandidatesRef.current.length > 0) {
          console.log('Adding queued ICE candidates after setting remote description');
          for (const candidate of pendingIceCandidatesRef.current) {
            console.log('准备添加ICE候选 (来电处理): current connectionState:', peerConnectionRef.current.connectionState, 'iceConnectionState:', peerConnectionRef.current.iceConnectionState);
            await peerConnectionRef.current.addIceCandidate(candidate);
            console.log('成功添加ICE候选 (来电处理):', candidate);
          }
          pendingIceCandidatesRef.current = [];
        }

        const answer = await peerConnectionRef.current.createAnswer();
        console.log('处理来电：创建应答后 signalingState:', peerConnectionRef.current.signalingState);
        await peerConnectionRef.current.setLocalDescription(answer);
        console.log('处理来电：设置本地描述后 signalingState:', peerConnectionRef.current.signalingState);
        socketRef.current?.emit('video-answer', {
          sdp: answer,
          to: remoteUserId,
          from: localUserId,
        });

        setIsCallActive(true);
        setIsIncomingCall(false);
        setCallStatus('通话中');
        setIsLocalVideoMain(false);
        pendingOfferRef.current = null;
        console.log('处理来电：成功完成');
      }
    } catch (err) {
      console.error('处理来电失败:', err);
      cleanupCall();
    }
  };

  const startCall = async () => {
    try {
      if (!peerConnectionRef.current) {
        peerConnectionRef.current = createPeerConnection(localStream);
        console.log('发起方：peerConnectionRef.current 已设置:', peerConnectionRef.current);
      }

      setIsOutgoingCall(true);
      setCallStatus('正在呼叫...');
      setIsLocalVideoMain(true);

      const offer = await peerConnectionRef.current.createOffer({
        offerToReceiveAudio: true,
        offerToReceiveVideo: true,
      });
      await peerConnectionRef.current.setLocalDescription(offer);
      console.log('发起方：设置本地描述后 signalingState:', peerConnectionRef.current.signalingState);

      // Add any queued ICE candidates after setting local description
      if (pendingIceCandidatesRef.current.length > 0) {
        console.log('Adding queued ICE candidates after setting local description');
        for (const candidate of pendingIceCandidatesRef.current) {
          console.log('准备添加ICE候选 (发起通话): current connectionState:', peerConnectionRef.current.connectionState, 'iceConnectionState:', peerConnectionRef.current.iceConnectionState);
          await peerConnectionRef.current.addIceCandidate(candidate);
          console.log('成功添加ICE候选 (发起通话):', candidate);
        }
        pendingIceCandidatesRef.current = [];
      }

      socketRef.current?.emit('video-offer', {
        sdp: offer,
        to: remoteUserId,
        from: localUserId,
      });
    } catch (err) {
      console.error('发起通话失败:', err);
      cleanupCall();
    }
  };

  const cleanupCall = () => {
    console.log('cleanupCall 被调用. Current signalingState:', peerConnectionRef.current?.signalingState);
    console.log('cleanupCall 被调用. Current iceConnectionState:', peerConnectionRef.current?.iceConnectionState);
    if (peerConnectionRef.current) {
      peerConnectionRef.current.close();
      peerConnectionRef.current = null;
    }
    setRemoteStream(null);
    setIsCallActive(false);
    setIsIncomingCall(false);
    setIsOutgoingCall(false);
    setCallStatus('');
    setIsLocalVideoMain(true);
    pendingOfferRef.current = null;
    pendingIceCandidatesRef.current = [];
  };

  const endCall = () => {
    socketRef.current?.emit('hangup', {
      to: remoteUserId,
      from: localUserId,
    });
    cleanupCall();
  };

  return (
    <View style={styles.container}>
      <View style={styles.videoContainer}>
        {localStream && (
          <RTCView
            streamURL={localStream.toURL()}
            style={isLocalVideoMain ? styles.mainVideo : styles.smallVideo}
            objectFit="cover"
            mirror={true}
          />
        )}
        {remoteStream && (
          <RTCView
            streamURL={remoteStream.toURL()}
            style={isLocalVideoMain ? styles.smallVideo : styles.mainVideo}
            objectFit="cover"
          />
        )}
        {!localStream && !remoteStream && 
          <Text style={styles.statusText}>等待视频流...</Text>
        }
      </View>
      <View style={styles.statusContainer}>
        {callStatus ? (
          <Text style={styles.statusText}>{callStatus}</Text>
        ) : null}
      </View>
      <View style={styles.controls}>
        {!isCallActive && !isIncomingCall && !isOutgoingCall ? (
          <TouchableOpacity 
            style={[styles.button, !isConnected && styles.disabledButton]} 
            onPress={startCall}
            disabled={!isConnected}
          >
            <Text style={styles.buttonText}>
              {isConnected ? '开始通话' : '连接中...'}
            </Text>
          </TouchableOpacity>
        ) : isCallActive ? (
          <TouchableOpacity style={[styles.button, styles.endButton]} onPress={endCall}>
            <Text style={styles.buttonText}>结束通话</Text>
          </TouchableOpacity>
        ) : isOutgoingCall ? (
          <TouchableOpacity style={[styles.button, styles.disabledButton]} disabled>
            <Text style={styles.buttonText}>等待对方接听...</Text>
          </TouchableOpacity>
        ) : isIncomingCall ? (
          <View style={styles.incomingCallControls}>
            <TouchableOpacity style={[styles.button, styles.endButton]} onPress={() => {
              socketRef.current?.emit('call-rejected', {
                to: remoteUserId,
                from: localUserId,
              });
              cleanupCall();
            }}>
              <Text style={styles.buttonText}>拒绝</Text>
            </TouchableOpacity>
            <TouchableOpacity style={styles.button} onPress={handleIncomingCall}>
              <Text style={styles.buttonText}>接受</Text>
            </TouchableOpacity>
          </View>
        ) : null}
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#000',
  },
  videoContainer: {
    flex: 1,
    position: 'relative',
    width: '100%',
    height: '100%',
    backgroundColor: '#000',
  },
  mainVideo: {
    position: 'absolute',
    top: 0,
    left: 0,
    width: '100%',
    height: '100%',
    backgroundColor: '#333',
    zIndex: 0,
  },
  smallVideo: {
    width: 100,
    height: 150,
    backgroundColor: '#333',
    borderRadius: 10,
    position: 'absolute',
    top: 20,
    right: 20,
    zIndex: 1,
  },
  statusContainer: {
    position: 'absolute',
    top: 40,
    left: 0,
    right: 0,
    alignItems: 'center',
  },
  statusText: {
    color: '#fff',
    fontSize: 16,
    backgroundColor: 'rgba(0,0,0,0.5)',
    paddingHorizontal: 20,
    paddingVertical: 10,
    borderRadius: 20,
  },
  controls: {
    padding: 20,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
  },
  incomingCallControls: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    width: '100%',
  },
  button: {
    backgroundColor: '#4CAF50',
    paddingHorizontal: 30,
    paddingVertical: 15,
    borderRadius: 25,
  },
  endButton: {
    backgroundColor: '#f44336',
  },
  disabledButton: {
    backgroundColor: '#999',
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: 'bold',
  },
});
